package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"sync"
	"sync/atomic"
	"time"

	"github.com/gorilla/websocket"
)

/*
	func main() {
		mu := sync.Mutex{}
		conns := []*websocket.Conn{}
		var count int64 = 0
		// 连接WebSocket服务器
		wg := &sync.WaitGroup{}
		for i := 0; i < 200; i++ {
			wg.Add(1)
			go func() {
				defer wg.Done()
				conn, _, err := websocket.DefaultDialer.Dial("ws://LAPTOP-J6QC41QI:10240/user/ws", nil)
				if err != nil {
					log.Fatal(err)
				}

				fmt.Println("建立websocket连接成功")

				mu.Lock()
				conns = append(conns, conn)
				mu.Unlock()
			}()
		}
		wg.Wait()
		fmt.Println("200 connections connected")

		// 发送消息
		for i := 0; i < 200; i++ {
			req := map[string]interface{}{}
			req["cmd"] = "chat"
			data := map[string]interface{}{}
			data["app_id"] = 1
			data["type"] = "text"
			data["msg"] = fmt.Sprintf("hello world %d", i)
			data["sender_id"] = 2
			data["reciever_id"] = 2
			data["time"] = 14894793249249

			req["data"] = data
			//requestData, _ := json.Marshal(req)
			//err := conns[i].WriteMessage(websocket.TextMessage, requestData)
			//if err != nil {
			//	log.Fatal(err)
			//}
		}

		// 读取消息
		for i := 0; i < 200; i++ {
			wg.Add(1)
			go func(j int) {
				defer wg.Done()
				for k := 0; k < 100; k++ {
					_, p, err := conns[j].ReadMessage()
					if err != nil {
						log.Fatal(err)
					}
					atomic.AddInt64(&count, 1)
					log.Printf("Received message: %s, count: %d", string(p), count)
				}
			}(i)
		}
		wg.Wait()
	}
*/
var count int64 = 0
var readCount int64 = 0

func main() {

	mu := sync.Mutex{}
	conns := make([]*websocket.Conn, 10000)

	wg := sync.WaitGroup{}
	for i := 1; i <= 500; i++ {
		wg.Add(1)
		go func(senderId int) {
			defer wg.Done()
			if !login(101, senderId, senderId) {
				return
			}

			conn := upgrade(senderId)

			mu.Lock()
			conns[senderId] = conn
			mu.Unlock()
		}(i)
	}

	wg.Wait()
	time.Sleep(5 * time.Second)

	go func() {
		for {
			fmt.Printf("接收总数: %d\n", readCount)
			time.Sleep(5 * time.Second)
		}
	}()

	go func() {
		for {
			fmt.Printf("发送总数: %d\n", count)
			time.Sleep(5 * time.Second)
		}
	}()

	for i := 1; i <= 500; i++ {
		// read
		go listenRead(conns[i], i)

		// write
		go listenWrite(conns[i], i)
	}

	time.Sleep(100 * time.Minute)
}

func login(appId int, senderId, password int) bool {

	res, err := http.Get(
		"http://" + "LAPTOP-J6QC41QI:10241/user/login" +
			fmt.Sprintf("?app_id=%d&user_id=%d&password=%d", appId, senderId, password),
	)

	if err != nil {
		fmt.Println(err.Error())

		return false
	}

	resp := make(map[string]interface{})
	// read http response body
	temp, err := io.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err.Error())

		return false
	}

	// unmashal body data into temp
	if err := json.Unmarshal(temp, &resp); err != nil {
		fmt.Println(err.Error())

		return false
	}

	//fmt.Println(resp)

	if int(resp["code"].(float64)) != 200 {
		fmt.Printf("登陆失败: %s\n\n", resp["code"])
		fmt.Printf("登陆失败: %s\n\n", resp["msg"])

		return false
	}

	fmt.Printf("%s, token: %s\n\n", resp["msg"], resp["data"])
	return true
}

func upgrade(senderId int) *websocket.Conn {

	// 升级为websocket连接
	conn, response, err := websocket.DefaultDialer.Dial(
		fmt.Sprintf("ws://LAPTOP-J6QC41QI:10241/user/ws?token=123&app_id=101&user_id=%d", senderId), nil)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(response)
	fmt.Println("建立websocket连接成功")
	return conn
}

func listenRead(conn *websocket.Conn, senderId int) {
	for {
		_, p, err := conn.ReadMessage()
		if err != nil {
			panic(err)
		}

		//if len(string(p)) > 100 {

		atomic.AddInt64(&readCount, 1)
		fmt.Printf("\n**************** new message ****************\n")
		fmt.Printf("接收者: %d\n", senderId)
		fmt.Printf("总数: %d\n", readCount)
		fmt.Printf("%s\n", string(p))
		fmt.Printf("*********************************************\n\n")
		//fmt.Printf("[发送消息]:\n")
		//fmt.Printf("To: ")
		//}
	}
}

// write
func listenWrite(conn *websocket.Conn, senderId int) {

	for i := 0; i < 1; i++ {
		req := map[string]interface{}{}
		req["cmd"] = "singleChat"
		data := map[string]interface{}{}
		data["app_id"] = uint32(101)
		data["type"] = "text"
		data["sender_id"] = senderId
		data["sent_time"] = time.Now().Unix()
		req["data"] = data
		data["reciever_id"] = senderId - 1
		data["content"] = fmt.Sprintf("hello %d, this is %d", senderId-1, senderId)

		requestData, _ := json.Marshal(req)
		if err := conn.WriteMessage(websocket.TextMessage, requestData); err != nil {
			fmt.Printf("发送消息失败: %s\n\n", err.Error())
			panic(err)
		}

		//fmt.Printf("To: %s, Content: %s\n\n", data["reciever_id"], data["content"])
		//}
		//time.Sleep(2 * time.Second)
		atomic.AddInt64(&count, 1)
		fmt.Printf("发送总数: %d\n", count)
	}
}
